package cn.yzj.openapi.exception;

import cn.yzj.openapi.common.FinalResult;
import cn.yzj.openapi.enums.error.ResultEnums;
import cn.yzj.openapi.utils.ReturnResultUtils;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;

/**
 * 异常处理器
 *
 * @author gzkemays
 * @since 2021/11/12 0:00
 */
@RestControllerAdvice
@Slf4j
public class OpenApiExceptionHandler {
  private static ImmutableMap<Class<? extends Throwable>, ResultEnums> EXCEPTIONS;
  protected static ImmutableMap.Builder<Class<? extends Throwable>, ResultEnums> BUILDER =
      ImmutableMap.builder();
  // 类加载时调用
  static {
    BUILDER.put(HttpRequestMethodNotSupportedException.class, ResultEnums.HTTP_REQ_NOT_SUPPORTED);
    BUILDER.put(HttpMessageNotReadableException.class, ResultEnums.DATA_ERROR);
    BUILDER.put(HttpMediaTypeNotSupportedException.class, ResultEnums.REQ_ERROR_SUPPORT);
    BUILDER.put(SQLSyntaxErrorException.class, ResultEnums.SQL_OPERA_ERROR);
    BUILDER.put(SQLException.class, ResultEnums.SQL_ERROR);
    BUILDER.put(NullPointerException.class, ResultEnums.NULL_POINTER_ERROR);
    BUILDER.put(IllegalArgumentException.class, ResultEnums.ILLEGAL_ARGS_ERROR);
  }

  @ExceptionHandler(value = OpenApiException.class)
  public FinalResult openApiException(OpenApiException exception) {
    log.error("错误异常信息 --> {}", exception.getMsg());
    return ReturnResultUtils.exception(exception);
  }

  @ExceptionHandler(value = MethodArgumentNotValidException.class)
  public FinalResult openApiException(MethodArgumentNotValidException ex) {
    log.error("错误异常信息 --> {}", ex.getMessage());
    BindingResult bindingResult = ex.getBindingResult();
    return ReturnResultUtils.validate(bindingResult);
  }

  @ExceptionHandler(value = BindException.class)
  public FinalResult openApiException(BindException ex) {
    log.error("错误异常信息 --> {}", ex.getMessage());
    BindingResult bindingResult = ex.getBindingResult();
    return ReturnResultUtils.validate(bindingResult);
  }

  @ExceptionHandler(value = Exception.class)
  public FinalResult exception(Exception exception) {
    log.error("错误原因信息 --> {}", String.valueOf(exception.getCause()));
    log.error("异常类信息 --> {}", exception.getClass());
    exception.printStackTrace();
    if (EXCEPTIONS == null) {
      // 构建 exceptions
      EXCEPTIONS = BUILDER.build();
    }
    ResultEnums enums = EXCEPTIONS.get(exception.getClass());
    if (enums == null) {
      log.error("未知信息 --> {}", exception.getMessage());
      exception.printStackTrace();
      return FinalResult.buildByResultEnums(ResultEnums.UNKNOWN_ERROR);
    } else {
      log.error("异常信息 --> {}", exception.getMessage());
      return FinalResult.buildByResultEnums(enums);
    }
  }
}
